/* Copyright 2001,2002,2003 NAH6 BV
 * All Rights Reserved
 *
 *  $Header: /var/lib/cvs/secphone/ui/ce/KillApp.cpp,v 1.5 2003/11/21 12:39:24 itsme Exp $
 *
 *
 * this module implements a trick to prevent the original phoneapp
 * from starting up again, while we are having a cryptophone call.
 *
 *  - the phoneapp will fail to initialize properly when we
 *    steal the exclusive access to the hangup and answer keys.
 *
 */

#include <windows.h>
#include <tchar.h>
#include <Tlhelp32.h>

#include "debug.h"

#include "xda_keys.h"

#ifndef _WIN32_WCE
#define CloseToolhelp32Snapshot CloseHandle
#endif


#ifdef _WIN32_WCE

// these structs are WCE specific kernel data structures.
// see platformbuilder for full description.
//
// I use them to find the correct instance of the iexplorer.exe app to kill.

typedef struct _tagHDATA {
    DWORD reserverd[6];
    DWORD pvObj;
    DWORD reserverd2;
} HDATA;
typedef struct _tagPROCESS {
    DWORD reserved[0x12];
    WCHAR *pcmdline;
} PROCESS;
extern "C" BOOL SetKMode(BOOL);
extern "C" DWORD SetProcPermissions(DWORD);
bool matchProcessCommandLine(HANDLE hProc, WCHAR *cmdstart)
{
    BOOL bMode = SetKMode(TRUE);
    DWORD dwPerm = SetProcPermissions(0xFFFFFFFF);

    HDATA *hdata= (HDATA *)(0x80000000+((DWORD)hProc&0x1ffffffc));
    PROCESS *pproc= (PROCESS *)hdata->pvObj;
    bool res= pproc->pcmdline!=NULL && wcsncmp(pproc->pcmdline, cmdstart, wcslen(cmdstart))==0;

    SetProcPermissions(dwPerm);
    SetKMode(bMode);

    return res;
}

void KillIexplorerLinkApp()
{
    WCHAR *szProcName= L"iexplore.exe";

    HANDLE hTH= CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);

    int res=0;

    PROCESSENTRY32 pe;
    pe.dwSize= sizeof(PROCESSENTRY32);

    if (Process32First(hTH, &pe))
    {
        do {

            if (wcsicmp(szProcName, pe.szExeFile)==0)               
            {
                res++;
                HANDLE hProc= OpenProcess(0, 0, pe.th32ProcessID);
                if (matchProcessCommandLine(hProc, L"secure:")
                    && TerminateProcess(hProc, 0))
                    res++;
                CloseHandle(hProc);
                break;
            }
        } while (Process32Next(hTH, &pe));
    }

    CloseToolhelp32Snapshot(hTH);

}
#endif

int KillApp(TCHAR *szProcName)
{
    HANDLE hTH= CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);

    int res=0;

    PROCESSENTRY32 pe;
    pe.dwSize= sizeof(PROCESSENTRY32);

    if (Process32First(hTH, &pe))
    {
        do {

            if (wcsicmp(szProcName, pe.szExeFile)==0)
            {
                res++;
                HANDLE hProc= OpenProcess(0, 0, pe.th32ProcessID);
                if (TerminateProcess(hProc, 0))
                    res++;
                CloseHandle(hProc);
                break;
            }
        } while (Process32Next(hTH, &pe));
    }

    CloseToolhelp32Snapshot(hTH);

    return res;
}


// cprog.exe is mentioned in the following apps:
//    - shell32.exe
//    - stk.exe
//    - aygshell.dll
//    - clacky.dll
//    - mxip_misc_200.exe

// maybe I should keep track if the most recent registerhotkey was successful, or not.
// to be able to try again.
void KillCProgExe(HWND hWnd)
{
	//Sleep(100);
    if (KillApp(L"cprog.exe")==2)
    {
        debug("killed phone app\n");
    }

    bool bRes= false;
    // registering this key will disable the cprog phone app.
	//Sleep(100);
    if (RegisterHotKey(hWnd, 1, 0, VK_HANGUP))
    {
        debug("successfully registered hangup key\n");
        bRes= true;
    }
    else
        debug("unsuccessful register hangup key ... %08lx\n", GetLastError());
	//Sleep(100);
    // registering this key will disable the cprog phone app.
    if (RegisterHotKey(hWnd, 2, 0, VK_ANSWER))
    {
        debug("successfully registered answer key\n");
        bRes= true;

    }
    else
        debug("unsuccessful register answer key ... %08lx\n", GetLastError());
/*
    if (bRes)
        MessageBeep(MB_ICONEXCLAMATION);
*/
}

void RestartCProgExe(HWND hWnd)
{
    // kill app before unregistering key, to prevent it from becoming active immediately.

    if (KillApp(L"cprog.exe")==2)
    {
        debug("killed phone app\n");
        MessageBeep(MB_ICONEXCLAMATION);
    }

    UnregisterHotKey(hWnd, 1);
    UnregisterHotKey(hWnd, 2);

    // restart cprog.exe with -n to make it active in the background
    CreateProcess( L"\\Windows\\cprog.exe", L"-n", 0, 0, 0, 0, 0, 0, 0, 0 );
    
}
